From: Alex Williamson Date: Wed, 17 Oct 2007 16:36:31 +0000 (-0600) Subject: [IA64] Backup/restore ACPI tables X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14861 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22Dat/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22Dat?a=commitdiff_plain;h=a0447f82ed657de9a161cacd120057868ad15795;p=xen.git [IA64] Backup/restore ACPI tables We modify some of the ACPI tables for dom0 (limiting available CPUs, modifying id/eid, and hiding SLIT/SRAT tables). This causes problems when we try to kexec with different dom0 CPU counts or from Xen to Linux. This introduces a mechanism to save ACPI tables before modification and restoring them before kexec. Signed-off-by: Alex Williamson Acked-by: Simon Horman --- diff --git a/xen/arch/ia64/xen/dom_fw_dom0.c b/xen/arch/ia64/xen/dom_fw_dom0.c index 7cfa69dd51..68a6bae630 100644 --- a/xen/arch/ia64/xen/dom_fw_dom0.c +++ b/xen/arch/ia64/xen/dom_fw_dom0.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -36,6 +37,15 @@ #include +struct acpi_backup_table_entry { + struct list_head list; + unsigned long pa; + unsigned long size; + unsigned char data[0]; +}; + +static LIST_HEAD(acpi_backup_table_list); + static u32 lsapic_nbr; /* Modify lsapic table. Provides LPs. */ @@ -100,18 +110,85 @@ acpi_update_madt_checksum(unsigned long phys_addr, unsigned long size) return 0; } +static int __init +acpi_backup_table(unsigned long phys_addr, unsigned long size) +{ + struct acpi_backup_table_entry *entry; + void *vaddr = __va(phys_addr); + + if (!phys_addr || !size) + return -EINVAL; + + entry = xmalloc_bytes(sizeof(*entry) + size); + if (!entry) { + dprintk(XENLOG_WARNING, "Failed to allocate memory for " + "%.4s table backup\n", + ((struct acpi_table_header *)vaddr)->signature); + return -ENOMEM; + } + + entry->pa = phys_addr; + entry->size = size; + + memcpy(entry->data, vaddr, size); + + list_add(&entry->list, &acpi_backup_table_list); + + printk(XENLOG_INFO "Backup %.4s table stored @0x%p\n", + ((struct acpi_table_header *)entry->data)->signature, + entry->data); + + return 0; +} + +void +acpi_restore_tables() +{ + struct acpi_backup_table_entry *entry; + + list_for_each_entry(entry, &acpi_backup_table_list, list) { + printk(XENLOG_INFO "Restoring backup %.4s table @0x%p\n", + ((struct acpi_table_header *)entry->data)->signature, + entry->data); + + memcpy(__va(entry->pa), entry->data, entry->size); + /* Only called from kexec path, no need to free entries */ + } +} + /* base is physical address of acpi table */ static void __init touch_acpi_table(void) { int result; lsapic_nbr = 0; + /* + * Modify dom0 MADT: + * - Disable CPUs that would exceed max vCPUs for the domain + * - Virtualize id/eid for indexing into domain vCPU array + * - Hide CPEI interrupt source + * + * ACPI tables must be backed-up before modification! + */ + acpi_table_parse(ACPI_APIC, acpi_backup_table); + if (acpi_table_parse_madt(ACPI_MADT_LSAPIC, acpi_update_lsapic, 0) < 0) printk("Error parsing MADT - no LAPIC entries\n"); if (acpi_table_parse_madt(ACPI_MADT_PLAT_INT_SRC, acpi_patch_plat_int_src, 0) < 0) printk("Error parsing MADT - no PLAT_INT_SRC entries\n"); + acpi_table_parse(ACPI_APIC, acpi_update_madt_checksum); + + /* + * SRAT & SLIT tables aren't useful for Dom0 until + * we support more NUMA configuration information in Xen. + * + * NB - backup ACPI tables first. + */ + acpi_table_parse(ACPI_SRAT, acpi_backup_table); + acpi_table_parse(ACPI_SLIT, acpi_backup_table); + result = acpi_table_disable(ACPI_SRAT); if ( result == 0 ) printk("Success Disabling SRAT\n"); @@ -124,8 +201,6 @@ static void __init touch_acpi_table(void) else if ( result != -ENOENT ) printk("ERROR: Failed Disabling SLIT\n"); - acpi_table_parse(ACPI_APIC, acpi_update_madt_checksum); - return; } @@ -133,9 +208,9 @@ void __init efi_systable_init_dom0(struct fw_tables *tables) { int i = 1; - /* Write messages to the console. */ touch_acpi_table(); + /* Write messages to the console. */ printk("Domain0 EFI passthrough:"); if (efi.mps) { tables->efi_tables[i].guid = MPS_TABLE_GUID; diff --git a/xen/arch/ia64/xen/machine_kexec.c b/xen/arch/ia64/xen/machine_kexec.c index 666dbc967a..b9c78fd9ed 100644 --- a/xen/arch/ia64/xen/machine_kexec.c +++ b/xen/arch/ia64/xen/machine_kexec.c @@ -23,6 +23,7 @@ #include #include #include +#include typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)( unsigned long indirection_page, @@ -149,6 +150,7 @@ static void machine_shutdown(void) } #endif kexec_disable_iosapic(); + acpi_restore_tables(); } void machine_kexec(xen_kexec_image_t *image) diff --git a/xen/include/asm-ia64/dom_fw_dom0.h b/xen/include/asm-ia64/dom_fw_dom0.h index 11e199cb5c..cc52c908b8 100644 --- a/xen/include/asm-ia64/dom_fw_dom0.h +++ b/xen/include/asm-ia64/dom_fw_dom0.h @@ -26,6 +26,7 @@ struct domain; void efi_systable_init_dom0(struct fw_tables *tables); int complete_dom0_memmap(struct domain *d, struct fw_tables *tables); +void acpi_restore_tables(void); #endif /* __ASM_IA64_DOM_FW_DOM0_H__ */ /*